import requests
import random
import time
import json

# 定义API接口URL
API_URL = "http://localhost:5000/api/recipe/nsga"

# 随机生成total_calories
def generate_total_calories():
    return random.randint(1200, 2000)

# 随机生成meal_count
def generate_meal_count():
    return random.choice([3, 4])

# 随机生成local
def generate_local():
    return random.choice(["广东", "上海", "北京", "湖南"])

# 随机生成food_type
def generate_food_type():
    return random.choice(["菜肴", "食材"])

# 随机生成营养素比例（保证每个营养素大于0.2，且比例和为1）
def generate_macronutrient_ratios():
    remaining = 1
    carb_ratio = random.uniform(0.2, remaining - 0.2)
    remaining -= carb_ratio
    protein_ratio = random.uniform(0.2, remaining - 0.2)
    fat_ratio = 1 - carb_ratio - protein_ratio
    return carb_ratio, protein_ratio, fat_ratio

# 随机生成meal_food_types
def generate_meal_food_types():
    return random.choice([4, 5, 6])

# 发送请求并获取结果
def send_request(total_calories, meal_count, carbohydrate_ratio, protein_ratio, fat_ratio, meal_food_types, local, food_type, user_id, date):
    params = {
        "total_calories": total_calories,
        "meal_count": meal_count,
        "carbohydrate_ratio": carbohydrate_ratio,
        "protein_ratio": protein_ratio,
        "fat_ratio": fat_ratio,
        "meal_food_types": meal_food_types,
        "local": local,
        "food_type": food_type,
        "user_id": user_id,
        "date": date
    }
    response = requests.get(API_URL, params=params)
    return response.json()

# 计算卡路里偏差
def calculate_calories_deviation(expected, actual):
    return abs(expected - actual)

# 计算宏观营养素比例的累积偏差
def calculate_macronutrient_deviation(expected_ratios, actual_ratios):
    return sum(abs(expected_ratios[i] - actual_ratios[i]) for i in range(3))

# 计算每餐食物种类比例的偏差
def calculate_meal_food_types_ratio(meal_food_types, actual_food_counts):
    count = sum(1 for food_count in actual_food_counts if food_count >= meal_food_types)
    return count / len(actual_food_counts)

# 计算测试指标
def run_test(user_id, date, num_tests=100):
    total_calories_deviations = []
    macronutrient_deviations = []
    meal_count_matches = []
    meal_food_type_ratios = []
    total_times = []

    # 记录结果
    with open("test_results.txt", "w", encoding="utf-8") as file:
        file.write("测试开始\n")

        for i in range(num_tests):
            print(i+1)
            # 生成随机参数
            total_calories = generate_total_calories()
            meal_count = generate_meal_count()
            local = generate_local()
            food_type = generate_food_type()
            carb_ratio, protein_ratio, fat_ratio = generate_macronutrient_ratios()
            meal_food_types = generate_meal_food_types()

            # 发送请求并记录时间
            start_time = time.time()
            response_data = send_request(
                total_calories, meal_count, carb_ratio, protein_ratio, fat_ratio, meal_food_types, local, food_type, user_id, date
            )
            end_time = time.time()

            # 记录生成时间
            total_times.append(end_time - start_time)

            # 获取响应结果
            daily_recipe = response_data.get('daily_recipe', {})
            meals = response_data.get('meals', [])

            if not daily_recipe or not meals:
                print(f"第{i+1}次请求失败，响应数据不完整")
                continue

            # 计算卡路里偏差
            total_day_calories = daily_recipe.get("total_day_calories", 0)
            calories_deviation = calculate_calories_deviation(total_calories, total_day_calories)
            total_calories_deviations.append(calories_deviation)

            # 计算宏观营养素比例的偏差
            actual_ratios = [daily_recipe.get("carbohydrate_ratio", 0), daily_recipe.get("protein_ratio", 0), daily_recipe.get("fat_ratio", 0)]
            macronutrient_deviation = calculate_macronutrient_deviation([carb_ratio, protein_ratio, fat_ratio], actual_ratios)
            macronutrient_deviations.append(macronutrient_deviation)

            # 计算每餐食物种类比例的偏差
            actual_food_counts = [len(meal.get("foodList", [])) for meal in meals]
            meal_food_type_ratio = calculate_meal_food_types_ratio(meal_food_types, actual_food_counts)
            meal_food_type_ratios.append(meal_food_type_ratio)

            # 记录是否满足meal_count
            meal_count_match = 1 if len(meals) == meal_count else 0
            meal_count_matches.append(meal_count_match)

            # 记录测试结果
            file.write(f"测试#{i+1}:\n")
            file.write(f"请求参数: total_calories={total_calories}, meal_count={meal_count}, local={local}, food_type={food_type}, meal_food_types={meal_food_types}\n")
            file.write(f"生成结果: 总卡路里={total_day_calories}, 宏观营养素比例={actual_ratios}\n")
            file.write(f"卡路里偏差={calories_deviation}, 宏观营养素偏差={macronutrient_deviation}, 食物种类比例={meal_food_type_ratio}\n")
            file.write("\n")

        # 计算平均生成时间
        average_time = sum(total_times) / len(total_times)

        # 计算各项指标
        average_calories_deviation = sum(total_calories_deviations) / len(total_calories_deviations)
        average_macronutrient_deviation = sum(macronutrient_deviations) / len(macronutrient_deviations)
        average_meal_count_match = sum(meal_count_matches) / len(meal_count_matches) if meal_count_matches else 0
        average_meal_food_type_ratio = sum(meal_food_type_ratios) / len(meal_food_type_ratios)

        # 保存总结果
        file.write("测试总结:\n")
        file.write(f"平均卡路里偏差: {average_calories_deviation}\n")
        file.write(f"平均宏观营养素偏差: {average_macronutrient_deviation}\n")
        file.write(f"平均生成时间: {average_time:.4f}秒\n")
        file.write(f"平均食物种类比例满足度: {average_meal_food_type_ratio}\n")
        file.write(f"平均餐数满足度: {average_meal_count_match}\n")

# 调用测试函数
if __name__ == "__main__":
    user_id = 1156
    date = "2024-12-19"
    run_test(user_id, date)
